package com.smileus.integration.caller.impl;

import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.smileus.common.Env;
import com.smileus.common.OneTask;
import com.smileus.entity.IntegrationLogs;
import com.smileus.entity.ServiceRouter;
import com.smileus.integration.caller.BatchCaller;
import com.smileus.service.ClusterService;
import com.smileus.service.IntegrationLogsService;

public class CxfBatchCaller implements BatchCaller {
	private static ServiceRouter cfgRouter = Env.getBean("serviceRouter", ServiceRouter.class);
	protected static ClusterService clusterService = Env.getBean("defaultClusterService", ClusterService.class);	private static Map<String, Client> CLIENT_MAP = new HashMap<String, Client>();

	/**
	 * 参数形式：{isBatch:true,tasks:[{"sId:userService.add,ps:[param,param]",seq:123
	 * }]}
	 * 
	 */
	public String batchCall(String url, List<OneTask> batchTask) {
		String result = null;
		JSONArray tasks = new JSONArray();
		for (OneTask oneTask : batchTask) {
			JSONObject task = new JSONObject();
			task.put("sId", oneTask.getCallInfo().getService());
			task.put("ps", oneTask.getCallInfo().getParams());
			task.put("seq", oneTask.getSeq());
			tasks.add(task);
		}
		IntegrationLogs logs = new IntegrationLogs();
		logs.setFromSys(cfgRouter.getSysDomain());
		logs.setFromHost(cfgRouter.getServiceHost());
		try {
			String inParam = tasks.toJSONString();
			logs.setInParam(inParam);
			logs.setToHost(toTargetHost(url));
			Client client = null;
			if (CLIENT_MAP.containsKey(url)) {
				client = CLIENT_MAP.get(url);
			} else {
				client = JaxWsDynamicClientFactory.newInstance().createClient(url);
				CLIENT_MAP.put(url, client);
			}
			Object[] objects = client.invoke("doBatch", inParam);
			Thread.sleep(22);// sleep多少合适？
			result = objects[0].toString();
			logs.setSuccess(1);
			logs.setOutParam(result);
			IntegrationLogsService.saveLogs(logs);
		} catch (ConnectException e) {
			// RPC调用异常处理
			// TODO :
			/**
			 **异常情况下保障高可用： 1.可以尝试调用其他机器的服务 2.如果超过规定次数，远程启动备用服务器 3.短信、邮件通知系统owner
			 */
			if (clusterService.incrementAndCheck(url)) {
				// TODO：启用备用机器
				ServiceRouter sRouter = clusterService.getServiceRouterByPubAddress(url);
				if (sRouter.getServiceStatus() == 1) {
					sRouter.setServiceStatus(-1);// 设置为不可用状态
					clusterService.saveOrUpdateServiceRouter(sRouter);
				}
				clusterService.clusterRefresh();
				clusterService.sendMessage(sRouter);// 短信邮件通知
			}
			// 记录异常日志
			logs.setSuccess(-1);
			logs.setOutParam(e.getMessage());
			e.printStackTrace();
			IntegrationLogsService.saveLogs(logs);
		} catch (SocketTimeoutException e) {
			// TODO:处理超时该怎么处理
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	private String toTargetHost(String url) {
		URL urlobj = null;
		try {
			urlobj = new URL(url);
		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new RuntimeException("资源地址解析出错.");
		}
		return urlobj.getHost();
	}
}
